package com.winning.devops.cloud.id.time.impl;

import com.winning.devops.cloud.id.time.TimeService;

import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

/**
 * @author chensj@winning.com.cn
 */
public abstract class AbstractTimeService implements TimeService {
    /**
     * 数据库时间的毫秒值
     */
    private long remoteTimeMillis;
    /**
     * 本地时间的毫秒值
     */
    private long localTimeMillis;
    /**
     * 同步间隔
     */
    private int sychInterval = 60000;
    /**
     * 区域
     */
    private TimeZone timeZone;
    /**
     *
     */
    private Locale locale;

    private int firstDayOfWeek = Calendar.MONDAY;

    public void setSychronizeInterval(int sychInterval) {
        this.sychInterval = sychInterval;
    }

    public void setTimeZone(TimeZone timeZone) {
        this.timeZone = timeZone;
    }

    public void setLocale(Locale locale) {
        this.locale = locale;
    }

    public void setFirstDayOfWeek(int firstDayOfWeek) {
        this.firstDayOfWeek = firstDayOfWeek;
    }

    public final void reset() {
        this.remoteTimeMillis = remoteTimeMillis();
        this.localTimeMillis = localTimeMillis();
    }

    protected long localTimeMillis() {
        return System.currentTimeMillis();
    }

    protected long remoteTimeMillis() {
        return System.currentTimeMillis();
    }

    /**
     * 时间间隔
     *
     * @return
     */
    private long interval() {
        return System.currentTimeMillis() - this.localTimeMillis;
    }

    public final synchronized long currentTimeMillis() {
        long l = interval();
        if (l > this.sychInterval) {
            reset();
        }

        return this.remoteTimeMillis + interval();
    }

    /**
     * 对比，判断是否需要重置主键
     *
     * @param calField        时间类型
     * @param oldTimeInMillis 对比值，时间的毫秒值(long)
     * @return boolean
     */
    public final boolean isCutoff(int calField, long oldTimeInMillis) {
        long l = currentTimeMillis();
        return isCutoff(calField, l, oldTimeInMillis);
    }

    /**
     * 对比，判断是否需要重置主键
     *
     * @param calField        时间类型
     * @param newTimeInMillis 当前时间的毫秒值
     * @param oldTimeInMillis 旧的时间的毫秒值
     * @return boolean
     */
    public final boolean isCutoff(int calField, long newTimeInMillis, long oldTimeInMillis) {
        return getCalendarField(calField, newTimeInMillis) - getCalendarField(calField, oldTimeInMillis) > 0;

    }

    /**
     * 获取Calendar
     * 判断timeZone和locale，如果设置则获取指定区域的Calendar，反之则获取默认的Calendar
     *
     * @return
     */
    private Calendar getCalendar() {
        Calendar cal = null;
        if ((this.timeZone != null) && (this.locale != null)) {
            cal = Calendar.getInstance(this.timeZone, this.locale);
        } else if (this.timeZone != null) {
            cal = Calendar.getInstance(this.timeZone);
        } else if (this.locale != null) {
            cal = Calendar.getInstance(this.locale);
        } else {
            cal = Calendar.getInstance();
        }
        cal.setFirstDayOfWeek(this.firstDayOfWeek);
        return cal;
    }

    /**
     * 获取指定{@code field}的值
     *
     * @param field        区域，比如时分秒
     * @param timeInMillis 时间的毫秒值
     * @return 域的值
     */
    private int getCalendarField(int field, long timeInMillis) {
        Calendar cal = getCalendar();
        cal.setTimeInMillis(timeInMillis);
        return cal.get(field);
    }
}
